package org.newtech.objectgrid.examples;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.ibm.websphere.objectgrid.ObjectGrid;
import com.ibm.websphere.objectgrid.Session;
import com.ibm.websphere.objectgrid.TxID;
import com.ibm.websphere.objectgrid.plugins.TransactionCallback;
import com.ibm.websphere.objectgrid.plugins.TransactionCallbackException;

/**
 * TransactionCallback object to use when MySqlLoader is used
 * as as a Loader for a BackingMap.
 */
public class CustomerTransactionCallback implements TransactionCallback {

    // first element is the Changes slot
    // second element is the Loader slot    
    private HashMap ivSlotsMap = new HashMap();
    
	/**
	 * 
	 */ 
	public CustomerTransactionCallback() 
	{
		super(); 
	}

	/* (non-Javadoc)
	 * @see com.ibm.websphere.objectgrid.plugins.TransactionCallback#initialize(com.ibm.websphere.objectgrid.ObjectGrid)
	 */
	public void initialize(ObjectGrid objectGrid) throws TransactionCallbackException
	{
       System.out.println("In MySqlTransactionCallback.initialize...");
        List maps = objectGrid.getListOfMapNames();
        for (int i = maps.size()-1; i >= 0; --i)  { 
            ivSlotsMap.put(maps.get(i), 
                           new int[] {objectGrid.reserveSlot(TxID.SLOT_NAME),
                                      objectGrid.reserveSlot(TxID.SLOT_NAME)});
        }
	}

	/* (non-Javadoc)
	 * @see com.ibm.websphere.objectgrid.plugins.TransactionCallback#begin(com.ibm.websphere.objectgrid.TxID)
	 */
	public void begin(TxID tx) throws TransactionCallbackException 
	{   
        Object[] mapEntries = ivSlotsMap.entrySet().toArray();
        for (int i = mapEntries.length-1; i >= 0; --i) {
            int [] value = (int[])((Map.Entry)mapEntries[i]).getValue();
            tx.putSlot( value[1], null );
        }
	}

	/* (non-Javadoc)
	 * @see com.ibm.websphere.objectgrid.plugins.TransactionCallback#commit(com.ibm.websphere.objectgrid.TxID)
	 */
	public void commit(TxID tx) throws TransactionCallbackException 
	{
		try
		{
            Object[] mapEntries = ivSlotsMap.entrySet().toArray();
            for (int i = mapEntries.length-1; i >= 0; --i) {
                int [] value = (int[])((Map.Entry)mapEntries[i]).getValue();
                CustomerLoader loader = (CustomerLoader) tx.getSlot( value[1] );
                if ( loader != null )
                {
                   HashMap changes = getChanges(tx, loader); 
                   loader.commit( tx, changes );
                }
            }
		}
		finally
		{
           cleanUpSlots(tx);
		}
	} 

	/* (non-Javadoc)
	 * @see com.ibm.websphere.objectgrid.plugins.TransactionCallback#rollback(com.ibm.websphere.objectgrid.TxID)
	 */
	public void rollback(TxID tx) throws TransactionCallbackException 
	{
        cleanUpSlots(tx);
	}
	
	/**
	 * @param tx
	 */
	private void cleanUpSlots(TxID tx) 
	{ 
        Object[] mapEntries = ivSlotsMap.entrySet().toArray();
        for (int i = mapEntries.length-1; i >= 0; --i) {
            int [] value = (int[])((Map.Entry)mapEntries[i]).getValue();
            tx.putSlot( value[0], null );
            tx.putSlot( value[1], null );
        }            
	}

	/**
	 * Initialize for calling back to a specific loader during commit.
	 * 
	 * @param loader is the cache loader to callback on during commit.
	 * @param committedMap contains the committed data to prime the changes map
	 *        with.  This only is done first time this method is called for
	 *        a given transaction.
	 */
	public void setLoader(TxID tx, CustomerLoader loader) 
	{  
        int [] value = (int[])ivSlotsMap.get(loader.getBackingMapName());
        HashMap changes = (HashMap) tx.getSlot( value[0] );
        if ( changes == null )
        {
            changes = new HashMap( new HashMap() );
            tx.putSlot( value[0], changes );
            tx.putSlot( value[1], loader );
        }            
	}

	/**
	 * Get the HashMap of changes made thus far for a specified
	 * transaction.
	 * 
	 * @param changes
	 */
	public HashMap getChanges(TxID tx, CustomerLoader loader) 
	{
        int [] value = (int[])ivSlotsMap.get(loader.getBackingMapName());
        return (HashMap) tx.getSlot(value[0]);
	}

	/* (non-Javadoc)
	 * @see com.ibm.websphere.objectgrid.plugins.TransactionCallback#isTransactionValid(com.ibm.websphere.objectgrid.Session)
	 */
	public boolean isExternalTransactionActive(Session session) {
		return false;
	}
}
